home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / networke / xfirepow.000 / xfirepow / xfirepower-0.84 / client / socket.c < prev   
C/C++ Source or Header  |  1995-11-22  |  18KB  |  831 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <sys/types.h>
  4. #include <sys/socket.h>
  5. #include <sys/time.h>
  6. #include <netinet/in.h>
  7. #include <arpa/inet.h>
  8. #include <netdb.h>
  9. #include <sys/errno.h>
  10. #include <sys/ioctl.h>
  11. #include <sys/file.h>
  12. #include <signal.h>
  13. #include <sys/wait.h>
  14. #include <sys/stat.h>
  15. #include <string.h>
  16. #include <unistd.h>
  17. #include <errno.h>
  18. #include <time.h>
  19. #ifdef _AIX
  20. #include <sys/select.h>
  21. #endif
  22. #include "data.h"
  23. #include "defs.h"
  24. #include "struct.h"
  25. #include "proto.h"
  26. #include "packet.h"
  27.  
  28. #ifdef UDP_PROXY
  29. int UdpProxyOpen(), UdpProxyRecv();
  30. #endif
  31.  
  32. static int udpLocalPort = 0, udpServerPort = 0;
  33. static int serveraddr = 0;
  34.  
  35. static int seq = 0;
  36. static struct timeval last_ping;
  37.  
  38. void
  39. callServer(port, server)
  40.     int     port;
  41.     char   *server;
  42. {
  43.     int     s;
  44.     struct sockaddr_in addr;
  45.     struct hostent *hp;
  46.  
  47.     printf("Calling %s on port %d.\n", server, port);
  48.     if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  49.     printf("I can't create a socket\n");
  50.     exit(0);
  51.     }
  52.  
  53.     addr.sin_family = AF_INET;
  54.     addr.sin_port = htons(port);
  55.  
  56.     if ((addr.sin_addr.s_addr = inet_addr(server)) == -1) {
  57.     if ((hp = gethostbyname(server)) == NULL) {
  58.         printf("Who is %s?\n", server);
  59.         exit(0);
  60.     } else {
  61.         addr.sin_addr.s_addr = *(long *) hp->h_addr;
  62.     }
  63.     }
  64.  
  65.     if (connect(s, (struct sockaddr *) & addr, sizeof(addr)) < 0) {
  66.     printf("Server not listening!\n");
  67.     exit(0);
  68.     }
  69.     printf("Got connection.\n");
  70.  
  71.     sock = s;
  72. }
  73.  
  74. int packetLength(char *buf)
  75. {
  76.     switch(buf[0]) {
  77.       case S_MAPINFO:
  78.     return sizeof(s_mapinfo) + (buf[1] * buf[2]);
  79.       case S_PERSONAL:
  80.     return sizeof(s_personal);
  81.       case S_POSITIONS:
  82.     return sizeof(s_positions) + (buf[1]&0x7f) * sizeof(s_oneposition);
  83.       case S_MESSAGE:
  84.     return sizeof(s_message);
  85.       case S_PLAYERDATA:
  86.     return sizeof(s_playerdata);
  87.       case S_PLAYERSTATS:
  88.     return sizeof(s_playerstats);
  89.       case S_SHELLINFO:
  90.     return sizeof(s_shellinfo);
  91.       case S_MAPSQUARE:
  92.     return sizeof(s_mapsquare);
  93.       case S_FLAG:
  94.     return sizeof(s_flag);
  95.       case S_UDPREPLY:
  96.     return sizeof(s_udpreply);
  97.       case S_MOTDLINE:
  98.     return sizeof(s_motdline);
  99.       case S_TEAMOK:
  100.     return sizeof(s_teamok);
  101.       case S_MINE:
  102.     return sizeof(s_mine);
  103.       case S_PLAYERINFO:
  104.       case S_SHELL:
  105.       case S_LOGIN:
  106.       default:
  107.     return 4;
  108.     }
  109. }
  110.  
  111. void handle_map(char *buf)
  112. {
  113.     int x, y;
  114.     s_mapinfo *pack = (s_mapinfo *)buf;
  115.     char *recvmap;
  116.  
  117.     map_info.m_width = pack->width;
  118.     map_info.m_height = pack->height;
  119.     strcpy(map_info.m_name, pack->name);
  120.  
  121.     recvmap = buf+sizeof(s_mapinfo);
  122.  
  123.     for(x=0;x<map_info.m_width;x++) {
  124.     for(y=0;y<map_info.m_width;y++) {
  125.         map[x][y] = recvmap[y*map_info.m_width + x];
  126.     }
  127.     }
  128.     map_pixel = 512/map_info.m_width;
  129.     if(300/map_info.m_height < map_pixel)
  130.     map_pixel = 300/map_info.m_height;
  131.     W_ResizeWindow(mapwin, map_info.m_width*map_pixel, map_info.m_height*map_pixel);
  132.     redrawmap = 1;
  133. }
  134.  
  135. void handle_personal(char *buf)
  136. {
  137.     s_personal *pack = (s_personal *)buf;
  138.  
  139.     me->p_x = ntohs(pack->x) << 4;
  140.     me->p_y = ntohs(pack->y) << 4;
  141.     me->p_status = pack->status;
  142.     me->p_dir = pack->dir & 0xf0;
  143.     me->p_speed = pack->dir & 0x0f;
  144.     me->p_damage = pack->damage;
  145.     me->p_ammo = pack->ammo;
  146.     me->p_fuel = ntohs(pack->fuel);
  147.     me->p_mines = (pack->mines & 0x1f);
  148.     me->p_trees = (pack->mines >> 5);
  149. }
  150.  
  151. void handle_positions(char *buf)
  152. {
  153.     s_positions *pack = (s_positions *)buf;
  154.     int cx, cy, dx, dy, i;
  155.     player *p;
  156.     s_oneposition *pos = (s_oneposition *)(pack+1);
  157.  
  158.     if(!(pack->num & 0x80)) {
  159.     cx = (me->p_x>>4)-WINWIDTH/2;
  160.     cy = (me->p_y>>4)-WINHEIGHT/2;
  161.     if(cx < 0) cx = 0;
  162.     else if(cx > GRIDWIDTH * map_info.m_width - WINWIDTH)
  163.         cx = GRIDWIDTH * map_info.m_width - WINWIDTH;
  164.     if(cy < 0) cy = 0;
  165.     else if(cy > GRIDHEIGHT * map_info.m_height - WINHEIGHT)
  166.         cy = GRIDHEIGHT * map_info.m_height - WINHEIGHT;
  167.     for(i=0;i<pack->num;i++) {
  168.         p = &players[(pos[i].num & 0x3f)];
  169.         dx = pos[i].lx;
  170.         dy = pos[i].ly;
  171.         if(pos[i].num & 0x80)
  172.         dx += 256;
  173.         if(pos[i].num & 0x40)
  174.         dy += 256;
  175.         p->p_x = (cx+dx) << 4;
  176.         p->p_y = (cy+dy) << 4;
  177.         p->p_dir = pos[i].dir;
  178.     }
  179.     } else {
  180.     for(i=0;i<(pack->num & 0x7f);i++) {
  181.         p=&players[(pos[i].num &0x3f)];
  182.         p->p_x = (pos[i].lx * GRIDWIDTH) << 4;
  183.         p->p_y = (pos[i].ly * GRIDWIDTH) << 4;
  184.         p->p_dir = pos[i].dir;
  185.     }
  186.     }
  187. }
  188.  
  189. void handle_playerinfo(char *buf)
  190. {
  191.     s_playerinfo *pack = (s_playerinfo *)buf;
  192.  
  193.     if(pack->status == PDEAD && players[(int)pack->num].p_status == PALIVE)
  194.     players[(int)pack->num].p_expfuse = EXPFUSE;
  195.     players[(int)pack->num].p_status = pack->status;
  196.     players[(int)pack->num].p_team = pack->team;
  197.     redraw_player_win();
  198. }
  199.  
  200. void handle_login(char *buf)
  201. {
  202.     s_login *pack = (s_login *)buf;
  203.     
  204.     me = &players[pack->num];
  205. }
  206.  
  207. void handle_shell(char *buf)
  208. {
  209.     s_shell *pack = (s_shell *)buf;
  210.     shell *s;
  211.     int cx, cy, dx, dy;
  212.  
  213.     cx = (me->p_x>>4)-WINWIDTH/2;
  214.     cy = (me->p_y>>4)-WINHEIGHT/2;
  215.     if(cx < 0) cx = 0;
  216.     else if(cx > GRIDWIDTH * map_info.m_width - WINWIDTH)
  217.     cx = GRIDWIDTH * map_info.m_width - WINWIDTH;
  218.     if(cy < 0) cy = 0;
  219.     else if(cy > GRIDHEIGHT * map_info.m_height - WINHEIGHT)
  220.     cy = GRIDHEIGHT * map_info.m_height - WINHEIGHT;
  221.  
  222.     dx = pack->lx;
  223.     dy = pack->ly;
  224.     if(pack->num & 0x80)
  225.     dx += 256;
  226.     if(pack->num & 0x40)
  227.     dy += 256;
  228.  
  229.     s = &shells[(pack->num & 0x3f)];
  230.     s->s_x = (cx+dx) << 4;
  231.     s->s_y = (cy+dy) << 4;
  232.     s->s_owner = (pack->num & 0x3f);
  233. }
  234.  
  235. void handle_message(char *buf)
  236. {
  237.     s_message *pack = (s_message *)buf;
  238.  
  239.     print_message(pack->message, pack->from, pack->to);
  240. }
  241.  
  242. void handle_playerdata(char *buf)
  243. {
  244.     s_playerdata *pack = (s_playerdata *)buf;
  245.  
  246.     strncpy(players[pack->num].p_name, pack->name, 16);
  247.     players[pack->num].p_name[15] = 0;
  248.     redraw_player_win();
  249. }
  250.  
  251. void handle_playerstats(char *buf)
  252. {
  253.     s_playerstats *pack = (s_playerstats *)buf;
  254.  
  255.     players[pack->num].p_wins = ntohl(pack->wins);
  256.     players[pack->num].p_losses = ntohl(pack->losses);
  257.     players[pack->num].p_kills = ntohl(pack->kills);
  258.     me->p_updateplayers |= (1 << pack->num);
  259. }
  260.  
  261. void handle_shellinfo(char *buf)
  262. {
  263.     s_shellinfo *pack = (s_shellinfo *)buf;
  264.  
  265.     shells[pack->num].s_status = pack->status;
  266.     shells[pack->num].s_fuse = 0;
  267. }
  268.  
  269. void handle_mapsquare(char *buf)
  270. {
  271.     s_mapsquare *pack = (s_mapsquare *)buf;
  272.      
  273.     map[pack->x][pack->y] = pack->value;
  274.     map_square(pack->x, pack->y);
  275. }
  276.  
  277. void handle_flag(char *buf)
  278. {
  279.     s_flag *pack = (s_flag *)buf;
  280.  
  281.     flags[pack->num].f_team = pack->team;
  282.     flags[pack->num].f_x = ntohs(pack->x) << 4;
  283.     flags[pack->num].f_y = ntohs(pack->y) << 4;
  284. }
  285.  
  286. void handle_UdpReply(char *buf)
  287. {
  288.     s_udpreply *pack = (s_udpreply *)buf;
  289.  
  290.     printf("Handling UDP Reply, server port = %d\n", ntohs(pack->port));
  291. }
  292.  
  293. void handle_motdline(char *buf)
  294. {
  295.     s_motdline *pack = (s_motdline *)buf;
  296.  
  297.     add_motd_line(ntohs(pack->line), pack->text);
  298. }
  299.  
  300. void handle_teamok(char *buf)
  301. {
  302.     s_teamok *pack = (s_teamok *)buf;
  303.  
  304.     teamOk = pack->teamok;
  305. }
  306.  
  307. void handle_mine(char *buf)
  308. {
  309.     s_mine *pack = (s_mine *)buf;
  310.     int n = ntohs(pack->num);
  311.  
  312.     if(pack->status == MIEMPTY) {
  313.     mines[n].mi_status = MIEXPLODE;
  314.     mines[n].mi_fuse = 0;
  315.     } else {
  316.     mines[n].mi_x = ntohs(pack->x) << 4;
  317.     mines[n].mi_y = ntohs(pack->y) << 4;
  318.     mines[n].mi_status = pack->status;
  319.     }
  320. }
  321.  
  322. void handle_ping(char *buf)
  323. {
  324.     s_ping *pack = (s_ping *)buf;
  325.     struct timeval now;
  326.     int usecs;
  327.     char mbuf[80];
  328.  
  329.     if(pack->seq != seq-1)
  330.     return;
  331.     
  332.     gettimeofday(&now, 0);
  333.     usecs=now.tv_usec - last_ping.tv_usec;
  334.     usecs += 1000000 * (now.tv_sec - last_ping.tv_sec);
  335.     sprintf(mbuf, "Ping time: %dms", usecs/1000);
  336.     print_message(mbuf, M_SRV, me->p_num);
  337. }
  338.  
  339. void doRead(int);
  340.  
  341. void doServer()
  342. {
  343.     fd_set read_fds;
  344.     int s;
  345.     struct timeval tv;
  346.  
  347.     FD_ZERO(&read_fds);
  348.     FD_SET(sock, &read_fds);
  349.     if(udpSock >= 0) {
  350.     FD_SET(udpSock, &read_fds);
  351.     }
  352.     tv.tv_sec = 0;
  353.     tv.tv_usec = UTIMER;
  354.  
  355. #if 0
  356.     while(1) {
  357.     if((s=select(32, &read_fds, 0, 0, &tv)) > 0) {
  358.         if(udpSock >= 0 && FD_ISSET(udpSock, &read_fds)) {
  359.         doRead(udpSock);
  360.         }
  361.         if(FD_ISSET(sock, &read_fds))
  362.         doRead(sock);
  363.     } else if(s == 0) {
  364.         break;
  365.     }
  366.     }
  367. #else
  368.     if((s=select(32, &read_fds, 0, 0, &tv)) > 0) {
  369.     if(udpSock >= 0 && FD_ISSET(udpSock, &read_fds)) {
  370.         doRead(udpSock);
  371.     }
  372.     if(FD_ISSET(sock, &read_fds))
  373.         doRead(sock);
  374.     }
  375. #endif
  376. }
  377.  
  378. void doRead(int asock)
  379. {    
  380.     static char *buf;
  381.     int in, pos, r;
  382.  
  383.     if(!buf)
  384.     buf = malloc(70000); /* I know it's stupid.  A large map can be 64k, this was the
  385.                 the easiest way to deal with it.  I suppose I could send
  386.                 the map one row per packet instead of one huge one... */
  387.     in = read(asock, buf, 1024);
  388.     if(in > 0) {
  389.     totalread += in;
  390.     pos = 0;
  391.     while(pos < in) {
  392. #ifdef DEBUG
  393.         printf("Packet length = %d, pos=%d, in=%d\n", packetLength(buf+pos), pos, in);
  394. #endif
  395.         while(in - pos < packetLength(buf+pos)) {
  396.         r = read(asock, buf+in, packetLength(buf+pos) - (in - pos));
  397.         if(r<=0) {
  398.             printf("Read error from server, exiting\n");
  399.             exit(0);
  400.         }
  401.         in += r;
  402.         totalread += r;
  403.         }
  404. #ifdef DEBUG
  405.         printf("Handling packet type %d\n", buf[pos]);
  406. #endif
  407.         switch(buf[pos]) {
  408.           case S_MAPINFO:
  409.         handle_map(&buf[pos]);
  410.         break;
  411.           case S_PERSONAL:
  412.         handle_personal(&buf[pos]);
  413.         break;
  414.           case S_POSITIONS:
  415.         handle_positions(&buf[pos]);
  416.         break;
  417.           case S_PLAYERINFO:
  418.         handle_playerinfo(&buf[pos]);
  419.         break;
  420.           case S_LOGIN:
  421.         handle_login(&buf[pos]);
  422.         break;
  423.           case S_SHELL:
  424.         handle_shell(&buf[pos]);
  425.         break;
  426.           case S_MESSAGE:
  427.         handle_message(&buf[pos]);
  428.         break;
  429.           case S_PLAYERDATA:
  430.         handle_playerdata(&buf[pos]);
  431.         break;
  432.           case S_PLAYERSTATS:
  433.         handle_playerstats(&buf[pos]);
  434.         break;
  435.           case S_SHELLINFO:
  436.         handle_shellinfo(&buf[pos]);
  437.         break;
  438.           case S_MAPSQUARE:
  439.         handle_mapsquare(&buf[pos]);
  440.         break;
  441.           case S_FLAG:
  442.         handle_flag(&buf[pos]);
  443.         break;
  444.           case S_UDPREPLY:
  445.         handle_UdpReply(&buf[pos]);
  446.         break;
  447.           case S_MOTDLINE:
  448.         handle_motdline(&buf[pos]);
  449.         break;
  450.           case S_TEAMOK:
  451.         handle_teamok(&buf[pos]);
  452.         break;
  453.           case S_MINE:
  454.         handle_mine(&buf[pos]);
  455.         break;
  456.           case S_PING:
  457.         handle_ping(&buf[pos]);
  458.         break;
  459.           default:
  460.         break;
  461.         }
  462.         pos += packetLength(buf+pos);
  463.     }
  464.     }
  465. }
  466.  
  467. int read_map()
  468. {
  469.     map_info.m_width = 0;
  470.  
  471.     while(map_info.m_width == 0) {
  472.     doServer();
  473.     }
  474.     return 1;
  475. }
  476.  
  477. void sendPacket(char *buf)
  478. {
  479.     int len;
  480.     int asock;
  481.  
  482.     asock = (udpSock >= 0) ? udpSock : sock;
  483.  
  484.     switch(buf[0]) {
  485.       case C_LOGIN:
  486.     len = sizeof(c_login);
  487.     asock = sock;
  488.     break;
  489.       case C_MESSAGE:
  490.     len = sizeof(c_message);
  491.     asock = sock;
  492.     break;
  493.       case C_UDPREQUEST:
  494.     len = sizeof(c_udprequest);
  495.     asock = sock;
  496.     break;
  497.       case C_PING:
  498.     len = sizeof(c_ping);
  499.     break;
  500.       case C_STEERING:
  501.       case C_SHELL:
  502.       case C_COURSE:
  503.       case C_SPEED:
  504.       default:
  505.     len = 4;
  506.     break;
  507.     }
  508.  
  509.     if(write(asock, buf, len) != len) {
  510.     printf("Connection to server lost, exiting\n");
  511.     quit = 1;
  512.     }
  513. }
  514.  
  515. void sendLogin(char *name, char *login)
  516. {
  517.     c_login pack;
  518.  
  519.     pack.type = C_LOGIN;
  520.     strncpy(pack.name, name, 15);
  521.     pack.name[15] = 0;
  522.     strncpy(pack.login, login, 15);
  523.     pack.login[15] = 0;
  524.     pack.version = htons(CLIENTVERSION);
  525.     sendPacket((char *)&pack);
  526. }
  527.  
  528. void sendSteering(int keys)
  529. {
  530.     c_steering pack;
  531.  
  532.     pack.type = C_STEERING;
  533.     pack.keys = keys;
  534.     sendPacket((char *)&pack);
  535. }
  536.  
  537. void sendShell()
  538. {
  539.     c_shell pack;
  540.  
  541.     pack.type = C_SHELL;
  542.     sendPacket((char *)&pack);
  543. }
  544.  
  545. void sendMessage(char *msg, int to)
  546. {
  547.     c_message pack;
  548.  
  549.     pack.type = C_MESSAGE;
  550.     pack.to = to;
  551.     strncpy(pack.message, msg, 79);
  552.     pack.message[79] = 0;
  553.     sendPacket((char *)&pack);
  554. }
  555.  
  556. void sendCourse(int course)
  557. {
  558.     c_course pack;
  559.  
  560.     pack.type = C_COURSE;
  561.     pack.dir = (UCHAR)course;
  562.     sendPacket((char *)&pack);
  563. }
  564.  
  565. void sendSpeed(int speed)
  566. {
  567.     c_speed pack;
  568.  
  569.     pack.type = C_SPEED;
  570.     pack.speed = speed;
  571.     sendPacket((char *)&pack);
  572. }
  573.  
  574. void sendTeam(int team)
  575. {
  576.     c_team pack;
  577.     
  578.     pack.type = C_TEAM;
  579.     pack.team = team;
  580.     sendPacket((char *)&pack);
  581. }
  582.  
  583. void sendMine()
  584. {
  585.     c_mine pack;
  586.     pack.type = C_MINE;
  587.     sendPacket((char *)&pack);
  588. }
  589.  
  590. void sendBuild(int terrain)
  591. {
  592.     c_build pack;
  593.     pack.type = C_BUILD;
  594.     pack.terrain = terrain;
  595.     sendPacket((char *)&pack);
  596. }
  597.  
  598. void sendPing()
  599. {
  600.     c_ping pack;
  601.  
  602.     pack.type = C_PING;
  603.     pack.seq = seq++;
  604.     sendPacket((char *)&pack);
  605.     gettimeofday(&last_ping, 0);
  606. }
  607.  
  608. #define MAX_PORT_RETRY  10
  609. static int
  610. openUdpConn()
  611. {
  612.     struct sockaddr_in addr;
  613.     struct hostent *hp;
  614.     int     attempts;
  615.  
  616. #ifdef UDP_PROXY
  617.     if(useUdpProxy)
  618.     return UdpProxyOpen();
  619. #endif
  620.  
  621.     if (udpSock >= 0) {
  622.     fprintf(stderr, "xfirepower: tried to open udpSock twice\n");
  623.     return (0);        /* pretend we succeeded (this could be bad) */
  624.     }
  625.     if ((udpSock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
  626.     perror("xfirepower: unable to create DGRAM socket");
  627.     return (-1);
  628.     }
  629.     addr.sin_addr.s_addr = INADDR_ANY;
  630.     addr.sin_family = AF_INET;
  631.  
  632.     errno = 0;
  633.     udpLocalPort = (getpid() & 32767) + (rand() % 256);
  634.     for (attempts = 0; attempts < MAX_PORT_RETRY; attempts++) {
  635.     while (udpLocalPort < 2048) {
  636.         udpLocalPort = (udpLocalPort + 10687) & 32767;
  637.     }
  638.     addr.sin_port = htons(udpLocalPort);
  639.     if (bind(udpSock, (struct sockaddr *) & addr, sizeof(addr)) >= 0)
  640.         break;
  641.     }
  642.     if (attempts == MAX_PORT_RETRY) {
  643.     perror("xfirepower: bind");
  644.     close(udpSock);
  645.     udpSock = -1;
  646.     return (-1);
  647.     }
  648.  
  649.     /* determine the address of the server */
  650.     if (!serveraddr) {
  651.     if ((addr.sin_addr.s_addr = inet_addr(server)) == -1) {
  652.         if ((hp = gethostbyname(server)) == NULL) {
  653.         printf("Who is %s?\n", server);
  654.         } else {
  655.         addr.sin_addr.s_addr = *(long *) hp->h_addr;
  656.         }
  657.     }
  658.     serveraddr = addr.sin_addr.s_addr;
  659.     }
  660.     return (0);
  661. }
  662.  
  663. static int
  664. recvUdpConn()
  665. {
  666.     fd_set  readfds;
  667.     struct timeval to;
  668.     struct sockaddr_in from;
  669.     int     fromlen, res;
  670.     char buf[1024];
  671.  
  672. #ifdef UDP_PROXY
  673.     if(useUdpProxy)
  674.     return UdpProxyRecv();
  675. #endif
  676.  
  677.     bzero(&from, sizeof(from));    /* don't get garbage if really broken */
  678.  
  679.     /* we patiently wait until the server sends a packet to us */
  680.     /* (note that we silently eat the first one) */
  681.     fromlen = sizeof(from);
  682.     FD_ZERO(&readfds);
  683.     FD_SET(udpSock, &readfds);
  684.     to.tv_sec = 6;        /* wait 3 seconds, then abort */
  685.     to.tv_usec = 0;
  686.     if ((res = select(32, &readfds, 0, 0, &to)) <= 0) {
  687.     if (!res) {
  688.         printf("UDP connection request timed out\n");
  689.         return (-1);
  690.     } else {
  691.         perror("select() before recvfrom()");
  692.         return (-1);
  693.     }
  694.     }
  695.     if (recvfrom(udpSock, buf, BUFSIZ, 0, (struct sockaddr *) & from, &fromlen) < 0) {
  696.     perror("recvfrom");
  697.     return (-1);
  698.     }
  699.     if (from.sin_addr.s_addr != serveraddr) {
  700.     /* safe? */
  701.     serveraddr = from.sin_addr.s_addr;
  702.     }
  703.     if (from.sin_family != AF_INET) {
  704.     ;
  705.     }
  706.     udpServerPort = ntohs(from.sin_port);
  707.  
  708.     if (connect(udpSock, (struct sockaddr *) & from, sizeof(from)) < 0) {
  709.     perror("xfirepower: unable to connect UDP socket after recvfrom()");
  710.     close(udpSock);
  711.     udpSock = -1;
  712.     return (-1);
  713.     }
  714.     return (0);
  715. }
  716.  
  717. int
  718. closeUdpConn()
  719. {
  720.     if (udpSock < 0) {
  721.     fprintf(stderr, "xfirepower: tried to close a closed UDP socket\n");
  722.     return (-1);
  723.     }
  724.     shutdown(udpSock, 2);
  725.     close(udpSock);
  726.     udpSock = -1;
  727.     return 0;
  728. }
  729.  
  730. void
  731. sendUdpRequest(req)
  732.     int     req;
  733. {
  734.     c_udprequest packet;
  735.  
  736.     packet.type = C_UDPREQUEST;
  737.     packet.mode = MODE_UDP;
  738.  
  739.     if (openUdpConn() >= 0) {
  740.     /* send the request */
  741.     packet.type = C_UDPREQUEST;
  742.     packet.mode = MODE_UDP;
  743.     packet.port = htons((unsigned)udpLocalPort);
  744.     sendPacket((char *) & packet);
  745.     if (recvUdpConn() < 0) {
  746.         printf("Couldn't open UDP connection\n");
  747.         closeUdpConn();
  748.     }
  749.     }
  750. }
  751.  
  752. #ifdef UDP_PROXY
  753. int UdpProxyOpen()
  754. {
  755.     int s, res;
  756.     struct sockaddr_in addr;
  757.     struct hostent *hp;
  758.     char buf[BUFSIZ], *ptr;
  759.  
  760.     printf("Using \"%s\" as the UDP proxy server address.\n", proxyServer);
  761.  
  762.     if((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  763.     perror("socket");
  764.     return(-1);
  765.     }
  766.  
  767.     addr.sin_family = AF_INET;
  768.     addr.sin_port = htons(proxyPort);
  769.  
  770.     if ((addr.sin_addr.s_addr = inet_addr(proxyServer)) == -1) {
  771.     if ((hp = gethostbyname(proxyServer)) == NULL) {
  772.         printf("Who is %s?\n", proxyServer);
  773.         return -1;
  774.     } else {
  775.         addr.sin_addr.s_addr = *(long *) hp->h_addr;
  776.     }
  777.     }
  778.  
  779.     if (connect(s, (struct sockaddr *) & addr, sizeof(addr)) < 0) {
  780.     printf("UDP Proxy server not listening!\n");
  781.     return -1;
  782.     }
  783.     printf("Got UDP Proxy connection.\n");
  784.  
  785.     udpSock = s;
  786.  
  787.     sprintf(buf, ": %s !", server);
  788.     write(udpSock, buf, strlen(buf));
  789.  
  790.     ptr = buf - 1;
  791.     while((*ptr != '!') && ptr < buf + BUFSIZ - 1) {
  792.     ptr++;
  793. loop:
  794.     if((res = read(udpSock, ptr, 1)) < 0) {
  795.         perror("read");
  796.         return -1;
  797.     }
  798.     if(res < 1) goto loop;
  799.  
  800.     *(ptr+1) = 0;
  801.     }
  802.  
  803.     if(sscanf(buf, "@ %d !", &udpLocalPort) != 1) {
  804.     printf("Couldn't scan UDP Proxy Local Port from \"%s\"\n", buf);
  805.     return -1;
  806.     }
  807.     return 0;
  808. }
  809.  
  810. int UdpProxyRecv()
  811. {
  812.     char buf[BUFSIZ];
  813.  
  814.     sprintf(buf, "UDP recvUdpConn !");
  815.     write(udpSock, buf, strlen(buf));
  816.  
  817.     if(read(udpSock, buf, 6) != 6) {
  818.     perror("read");
  819.     close(udpSock);
  820.     udpSock = -1;
  821.     }
  822.  
  823.     if(strncmp(buf, "UDPGO!", 6) != 0) {
  824.     printf("UDP Proxy connection unsuccessful, result was \"%s\"\n", buf);
  825.     close(udpSock);
  826.     udpSock = -1;
  827.     }
  828.     return 0;
  829. }
  830. #endif
  831.